package net.vinote.smart.platform.service.filter;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.Map;
import java.util.logging.Level;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.vinote.smart.platform.comm.DateFunction;
import net.vinote.smart.platform.comm.PlatformConst;
import net.vinote.smart.platform.module.database.DBFactory;
import net.vinote.smart.platform.module.i18n.Message;
import net.vinote.smart.platform.module.log.LoggerConfig;
import net.vinote.smart.platform.module.log.RunLogger;
import net.vinote.smart.platform.module.security.PlatformSecurity;
import net.vinote.smart.platform.service.SRE;
import net.vinote.smart.platform.service.bean.CodeLibrary;
import net.vinote.smart.platform.service.bean.User;
import net.vinote.smart.platform.service.enumerate.CodeCatalogEnum;
import net.vinote.smart.platform.timer.SystemTaskMonitorTask;
import net.vinote.smart.platform.timer.TimerManager;

import org.json.JSONObject;

public class SRELoadFilter implements Filter {

	private String encoding;

	private String[] dispatcherPattern = { ".html", ".json", ".jsp" };
	private String[] blankPath = { "/timeout.jsp", "/login.jsp",
			"/userRegister.jsp", "/runJavaMethod.json" };

	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletResponse response = (HttpServletResponse) resp;
		WrapperRequest request = new WrapperRequest(req);
		String path = request.getServletPath();
		HttpSession session = request.getSession();
		if (encoding != null) {
			req.setCharacterEncoding(encoding);
			resp.setCharacterEncoding(encoding);
		}
		for (String blank : blankPath) {
			if (path.startsWith(blank)) {
				chain.doFilter(request, response);
				return;
			}
		}
		if (path.equals("/datawindow_page.html")
				&& "system.license_regist_info.page".equals(request
						.getParameter("pagePath"))) {
			chain.doFilter(request, response);
			return;
		}
		for (String sessionPath : dispatcherPattern) {
			if (path.endsWith(sessionPath)) {
				User user = (User) session.getAttribute("user");
				if (user == null) {
					response.sendRedirect(request.getContextPath()
							+ "/timeout.jsp");
					return;
				}
				if (!SRE.getInstance().hasLicense()) {
					response.sendRedirect(request.getContextPath()
							+ "/datawindow_page.html?pagePath=system.license_regist_info.page");
					return;
				}
				break;
			}
		}
		chain.doFilter(request, response);
	}

	public void init(FilterConfig config) throws ServletException {
		String configFile = config.getInitParameter("file");
		ServletContext context = config.getServletContext();
		String basefile = context.getRealPath("/") + File.separator + "WEB-INF"
				+ File.separator;
		String sreFile = null;
		if (configFile != null) {
			sreFile = basefile + configFile;
		}
		context.setAttribute("SREFILE", sreFile);
		SRE sre = SRE.getInstance();

		// 初始化日志
		LoggerConfig logConfig = new LoggerConfig();
		if (logConfig.load(basefile + "runlogger.ini")) {
			String logDir = logConfig.getLogDir();
			if (logDir.startsWith("WEB-INF")) {
				logConfig.setLogDir(context.getRealPath("/") + logDir);
			}
			RunLogger.getLogger().init(logConfig);
		} else {
			throw new ServletException("Init Log System Fail");
		}

		RunLogger.getLogger().log(Level.FINE, "load SRE config");
		try {
			sre.loadCfg(new FileInputStream(sreFile));
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
			System.exit(-1);
		}// 先加载配置文件
		boolean flag = false;
		try {
			flag = sre.initializ();
		} catch (SQLException e) {
			RunLogger.getLogger().log(Level.SEVERE, e.getMessage(), e);
		}
		if (flag) {
			RunLogger.getLogger().log(Level.FINE, "load SRE config success");
			encoding = SRE.getAttribute("config.encoding").toString();

			// 初始化系统业务量
			/*
			 * SerialNoManager.getInstance().setMaxSize(
			 * SRE.getSystemParameter().getServiceCapacity());
			 */

			// 初始化国际化资源
			Message msg = SRE.getI18nMessage();
			msg.addI18N(SRE.getSystemParameter().getI18nPath(), null);
			context.setAttribute("msg", msg.getMessage());

			// 检查是否已注册该系统
			checkResister();
			if (!SRE.getInstance().hasLicense()) {
				RunLogger.getLogger().log(Level.WARNING, "has no license");
				return;
			}
			try {
				TimerManager.getInstance().schedule("TaskAutoStart", 0,
						System.currentTimeMillis() + 3000, 0,
						SystemTaskMonitorTask.class.getName());
			} catch (Exception e) {
				RunLogger.getLogger().log(e);
			}
		} else {
			RunLogger.getLogger().log(Level.WARNING, "load SRE config fail");
		}
	}

	private void checkResister() {
		try {
			Map<String, CodeLibrary> map = SRE
					.getCodeItems(CodeCatalogEnum.RegistrationCode.getCode());
			if (map == null || map.isEmpty()) {
				return;// 未注册
			}
			// 校验是否可正常使用
			String hardwareAddress = PlatformSecurity.getHardwareAddress();
			CodeLibrary lib = map.get(hardwareAddress);
			if (lib == null) {
				return;// 未注册
			}

			JSONObject json = new JSONObject(lib.getAttr01());

			String registUser = json.getString("user");
			String expireDate = json.getString("expire");
			String token = json.getString("token");
			// 校验信息合法性
			String regCode = PlatformSecurity.generateRegistrationCode(
					registUser, expireDate);
			Date now = new Date();
			if (token.equals(regCode)// 注册码正确
					&& DateFunction.getDate(expireDate, "yyyy-MM-dd")// 未过期
							.getTime() > now.getTime()) {
				SRE.getInstance().setLicense(true);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void destroy() {
		try {
			DBFactory.getFactory().destroy();
			DriverManager.deregisterDriver(DriverManager.getDriver(SRE
					.getAttribute(PlatformConst.SYSTEM_CFG_DATABASE_URL)
					.toString()));
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
